import requests
from lxml import etree
 
# 用于存放从网站上抓取到的所有ip地址；
all_ip_list = []
# 用于存放通过检测ip后可以使用的ip地址；
available_ip_list = []
 
# 设置一个请求头来伪装成浏览器；
def request_header():
    headers = {
        # 'User-Agent': UserAgent().random #常见浏览器的请求头伪装（如：火狐,谷歌）
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
    }
    return headers
 
# 检测ip是否可以使用
def check_ip(proxy):
    # 构建代理ip
    proxies = {
        "http": "http://" + proxy,
        "https": "https://" + proxy,
    }
    try:
        # 通过代理访问测试网站，设置timeout，使响应等待2s
        response = requests.get(url='http://www.techlabplt.com/', headers=request_header(), proxies=proxies, timeout=2)
        response.close()
        if response.status_code == 200:
            available_ip_list.append(proxy)
            print(proxy, '可以使用!')
        else:
            print(proxy, '超时，此地址无效!')
    except:
        print(proxy, '请求异常,此地址无效!')
 
def get_available_ips():
    # 爬取测试代理网站上的数据
    response = requests.get(url=f'http://www.techlabplt.com:8080/BD-PC/proxy.html', headers=request_header())
    text = response.text
    # 使用xpath解析，提取出数据ip，端口
    html = etree.HTML(text)
    # 通过xpath,获取table内的可用的ip地址，端口等信息
    tr_list = html.xpath('/html/body/div[3]/div[2]/div/div[2]/table/tbody/tr')
 
    # 循环遍历每一条数据
    for td in tr_list:
        # 获取ip
        ip_ = td.xpath('./td[1]/text()')[0]
        # 获取端口
        port = td.xpath('./td[2]/text()')[0]
        proxy = ip_ + ':' + port
        all_ip_list.append(proxy)
        # 检测获取到的ip是否可以使用
        check_ip(proxy)
 
# 代理地址存储到文件中
def save_file(file_path):
    proxy_file = open(file_path, 'w', encoding='utf-8')
    for ip in available_ip_list:
        proxy_file.write(ip + '\n')
    proxy_file.close()
 
# 主程序
if __name__ == '__main__':
    get_available_ips()
    print('爬取已完成！')
    print(f'爬取到的IP地址个数为：{len(all_ip_list)}')
    print(f'可以使用的IP个数为：{len(available_ip_list)}')
    file_path = "C:/lab/proxy.txt";
    save_file(file_path)
    print('代理IP地址列表已保存到：', file_path)
